/**
 * @file logger_benchmark.cpp
 * @brief 日志记录器性能基准测试程序
 * 
 * @details 该程序用于测试和比较不同类型日志记录器实现的性能，
 * 包括原始日志记录器（Logger）和优化版日志记录器（OptLogger）。
 * 通过测量记录随机字符串的CPU时钟周期数来评估性能。
 */

#include "common/logging.h"
#include "common/opt_logging.h"

/**
 * @brief 生成指定长度的随机字符串
 * 
 * @param length 要生成的字符串长度
 * @return std::string 生成的随机字符串
 * 
 * @details 该函数使用数字、大小写字母组成的字符集生成随机字符串。
 * 它定义了一个内部lambda函数randchar，用于生成单个随机字符，
 * 然后使用std::generate_n填充指定长度的字符串。
 */
std::string random_string(size_t length) {
  /**
   * @brief 生成随机字符的lambda函数
   * 
   * @details 定义一个包含数字、大小写字母的字符集，并从中随机选择一个字符返回。
   */
  auto randchar = []() -> char {
    const char charset[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";
    const size_t max_index = (sizeof(charset) - 1);
    return charset[rand() % max_index];
  };
  
  // 创建指定长度的字符串并使用随机字符填充
  std::string str(length, 0);
  std::generate_n(str.begin(), length, randchar);
  return str;
}

/**
 * @brief 测量日志记录器性能的函数
 * 
 * @tparam T 日志记录器类型，可以是Logger或OptLogger
 * @param logger 日志记录器对象指针
 * @return size_t 每个日志记录操作的平均CPU时钟周期数
 * 
 * @details 该函数对指定类型的日志记录器进行性能测试，通过生成随机字符串并记录到日志中，
 * 测量每个操作所需的CPU时钟周期数。使用rdtsc（Read Time-Stamp Counter）指令获取
 * 高精度的CPU时钟计数。最终返回所有操作的平均时钟周期数。
 */
template<typename T>
size_t benchmarkLogging(T *logger) {
  /**
   * @brief 测试循环次数
   * 
   * @details 定义每个测试运行的操作数量，设置为100,000次以确保测试结果的统计显著性。
   */
  constexpr size_t loop_count = 100000;
  
  /**
   * @brief 累计的CPU时钟周期数
   * 
   * @details 用于累计所有日志记录操作的CPU时钟周期数，最终将除以操作数量得到平均值。
   */
  size_t total_rdtsc = 0;
  
  /**
   * @brief 执行测试循环
   * 
   * @details 循环执行指定次数的日志记录操作，并测量每个操作的执行时间。
   * 每次循环生成一个128字符长度的随机字符串，并记录到日志中。
   */
  for (size_t i = 0; i < loop_count; ++i) {
    // 生成128字符长度的随机字符串
    const auto s = random_string(128);
    
    // 记录开始时间，执行日志记录操作，然后计算所用的时钟周期数
    const auto start = Common::rdtsc();
    logger->log("%\n", s);
    total_rdtsc += (Common::rdtsc() - start);
  }

  /**
   * @brief 计算并返回平均时钟周期数
   * 
   * @details 将总时钟周期数除以操作数量，得到每个日志记录操作的平均时钟周期数。
   */
  return (total_rdtsc / loop_count);
}

/**
 * @brief 程序的主函数
 * 
 * @param int 未使用的命令行参数数量
 * @param char** 未使用的命令行参数数组
 * @return int 程序退出状态码
 * 
 * @details 主函数测试两种不同的日志记录器实现（原始版和优化版）的性能，
 * 并输出每种实现的平均操作时钟周期数。在测试之间添加了睡眠时间，
 * 以确保日志文件写入完成并避免测试之间的干扰。
 */
int main(int, char **) {
  /**
   * @brief 引入时间字面量命名空间
   * 
   * @details 引入std::literals::chrono_literals命名空间，使用时间字面量（如"10s"表示10秒）
   * 来简化时间相关的代码。
   */
  using namespace std::literals::chrono_literals;

  /**
   * @brief 测试原始版日志记录器（Logger）
   * 
   * @details 创建原始版日志记录器实例，运行基准测试，并输出每个操作的平均时钟周期数。
   * 使用若干作用域确保日志记录器对象在测试完成后被自动释放。
   * 测试后睡眠10秒，确保日志文件写入完成。
   */
  {
    Common::Logger logger("logger_benchmark_original.log");
    const auto cycles = benchmarkLogging(&logger);
    std::cout << "ORIGINAL LOGGER " << cycles << " CLOCK CYCLES PER OPERATION." << std::endl;
    std::this_thread::sleep_for(10s); // 等待10秒确保日志写入完成
  }

  /**
   * @brief 测试优化版日志记录器（OptLogger）
   * 
   * @details 创建优化版日志记录器实例，运行基准测试，并输出每个操作的平均时钟周期数。
   * 使用若干作用域确保日志记录器对象在测试完成后被自动释放。
   * 测试后睡眠10秒，确保日志文件写入完成。
   */
  {
    OptCommon::OptLogger opt_logger("logger_benchmark_optimized.log");
    const auto cycles = benchmarkLogging(&opt_logger);
    std::cout << "OPTIMIZED LOGGER " << cycles << " CLOCK CYCLES PER OPERATION." << std::endl;
    std::this_thread::sleep_for(10s); // 等待10秒确保日志写入完成
  }

  /**
   * @brief 程序成功退出
   * 
   * @details 使用EXIT_SUCCESS状态码表示程序成功执行并正常退出。
   */
  exit(EXIT_SUCCESS);
}
